using System;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;

namespace LiteRP
{
    public partial class LiteRenderGraphRecorder : IRenderGraphRecorder, IDisposable
    {
        private static readonly ShaderTagId s_ShaderTagId = new ShaderTagId("SRPDefaultUnlit");
        public static ShaderTagId ShaderTagId { get { return s_ShaderTagId; } }
        
        private RTHandle m_TargetColorRTHandle;
        private TextureHandle m_BackbuffColorTextureHandle;
        
        
        private RTHandle m_TargetDepthRTHandle;
        private TextureHandle m_BackbuffDepthTextureHandle;
        
        public void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
        {
            CameraData cameraData = frameData.Get<CameraData>();
            CreateRenderGraphCameraRenderTargets(renderGraph, cameraData);
            AddSetupCameraPropertiesPass(renderGraph, cameraData);
            CameraClearFlags clearFlags = cameraData.camera.clearFlags;
            if ((!renderGraph.nativeRenderPassesEnabled && clearFlags != CameraClearFlags.Nothing) )
            {
                AddClearRenderTargetPass(renderGraph, cameraData);
            }
            
            AddDrawOpaqueObjectsPass(renderGraph, cameraData);

            if (clearFlags == CameraClearFlags.Skybox && RenderSettings.skybox != null)
            {
                AddDrawSkyboxPass(renderGraph, cameraData);
            }

            AddDrawTransparentObjectsPass(renderGraph, cameraData);
            #if UNITY_EDITOR
            AddDrawEditorGizmoPass(renderGraph, cameraData, GizmoSubset.PreImageEffects);
            AddDrawEditorGizmoPass(renderGraph, cameraData, GizmoSubset.PostImageEffects);
            #endif
        }

        public void Dispose()
        {
            RTHandles.Release(m_TargetColorRTHandle);
            m_TargetColorRTHandle = null;
            
            RTHandles.Release(m_TargetDepthRTHandle);
            m_TargetDepthRTHandle = null;
            GC.SuppressFinalize(this);
            
        }

        // 创建渲染贴图
        private void CreateRenderGraphCameraRenderTargets(RenderGraph renderGraph, CameraData cameraData)
        {
            var cameraTargetTexture = cameraData.camera.targetTexture;
            var isBuildInTexture = cameraTargetTexture == null;
            var isCameraTargetOffscreenDepth = !isBuildInTexture && cameraTargetTexture.format == RenderTextureFormat.Depth;
            
            RenderTargetIdentifier targetColorId = isBuildInTexture ? BuiltinRenderTextureType.CameraTarget : new RenderTargetIdentifier((cameraTargetTexture));
            if (m_TargetColorRTHandle == null)
            {
                m_TargetColorRTHandle = RTHandles.Alloc(targetColorId, "Backbuffer Color");
            }
            else if (m_TargetColorRTHandle.nameID != targetColorId)
            {
                RTHandleStaticHelpers.SetRTHandleUserManagedWrapper(ref m_TargetColorRTHandle, targetColorId);
            }
            
            RenderTargetIdentifier targetDepthId = isBuildInTexture ? BuiltinRenderTextureType.Depth : new RenderTargetIdentifier((cameraTargetTexture)); 
            if (m_TargetDepthRTHandle == null)
            {
                m_TargetDepthRTHandle = RTHandles.Alloc(targetDepthId, "Backbuffer Depth");
            }
            else if (m_TargetDepthRTHandle.nameID != targetDepthId)
            {
                RTHandleStaticHelpers.SetRTHandleUserManagedWrapper(ref m_TargetDepthRTHandle, targetDepthId);
            }
            

            bool clearOnFirstUse = ! renderGraph.nativeRenderPassesEnabled;
            bool discardOnLastUseColor = ! renderGraph.nativeRenderPassesEnabled;
            bool discardOnLastUseDepth = !isCameraTargetOffscreenDepth;
            
            ImportResourceParams importBackbufferColorParams= new ImportResourceParams();
            importBackbufferColorParams.clearOnFirstUse = clearOnFirstUse;
            importBackbufferColorParams.clearColor = cameraData.GetClearColor();
            importBackbufferColorParams.discardOnLastUse = discardOnLastUseColor;
            
            bool colorRT_sRGB = QualitySettings.activeColorSpace == ColorSpace.Linear;
            RenderTargetInfo importInfoColor = new RenderTargetInfo();
            if (isBuildInTexture)
            {
                importInfoColor.width = Screen.width;
                importInfoColor.height = Screen.height;
                importInfoColor.volumeDepth = 1;
                importInfoColor.msaaSamples = 1;
                importInfoColor.format = GraphicsFormatUtility.GetGraphicsFormat(RenderTextureFormat.Default, colorRT_sRGB);
                importInfoColor.bindMS = false;
            }
            else
            {
                importInfoColor.width = cameraTargetTexture.width;
                importInfoColor.height = cameraTargetTexture.height;
                importInfoColor.volumeDepth = cameraTargetTexture.volumeDepth;
                importInfoColor.msaaSamples = cameraTargetTexture.antiAliasing;
                importInfoColor.format = cameraTargetTexture.graphicsFormat;
                importInfoColor.bindMS = cameraTargetTexture.bindTextureMS;
            }


            m_BackbuffColorTextureHandle = renderGraph.ImportTexture(m_TargetColorRTHandle, importInfoColor, importBackbufferColorParams);
            
            
            ImportResourceParams importBackbufferDepthParams= new ImportResourceParams();
            importBackbufferDepthParams.clearOnFirstUse = clearOnFirstUse;
            importBackbufferDepthParams.clearColor = Color.black;
            importBackbufferDepthParams.discardOnLastUse = discardOnLastUseDepth;
            
            #if UNITY_EDITOR
            if (cameraData.camera.cameraType == CameraType.SceneView)
            {
                importBackbufferDepthParams.discardOnLastUse = false;
            }
            #endif
            
            RenderTargetInfo importInfodepth = importInfoColor;
            importInfodepth.format = SystemInfo.GetGraphicsFormat(DefaultFormat.DepthStencil);
            m_BackbuffDepthTextureHandle = renderGraph.ImportTexture(m_TargetDepthRTHandle, importInfodepth, importBackbufferDepthParams);
        }

        private void SetRenderAttachment(IRasterRenderGraphBuilder builder)
        {
            if (m_BackbuffColorTextureHandle.IsValid())
            {
                builder.SetRenderAttachment(m_BackbuffColorTextureHandle, 0, AccessFlags.Write);
            }
            
            if (m_BackbuffDepthTextureHandle.IsValid())
            {
                builder.SetRenderAttachmentDepth(m_BackbuffDepthTextureHandle, AccessFlags.Write);
            }
        }
    }
}